home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Utilities ƒ / MPW Tools ƒ / MakeMake / Source / Makemake.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-12-10  |  12.4 KB  |  513 lines  |  [TEXT/MPS ]

  1. # include "defs.h"
  2. # include "Types.h"
  3. # include "OSEvents.h"
  4. # include "Packages.h"
  5.  
  6. static char *dpndfile;    /* Name of temporary file            */
  7. static FILE *dpndf;        /* Read/write pointer to dpndfile    */
  8.  
  9. /*
  10.  * generate the makefile from information previously recorded
  11.  * in the global data structures.
  12.  * Write the output to the file whose name is recorded in the
  13.  * macro "MAKEFILE".
  14.  */
  15. makemake (argc, argv)
  16. int argc;            /* Number of command line arguments        */
  17. char *argv[];        /* The command line arguments            */
  18.     {
  19.     int i;            /* Loop counter                            */
  20.     int t;            /* Loop counter for targets[]            */
  21.     int numt;        /* Number of targets                    */
  22.     FILE *out;        /* Output file pointer                    */
  23.     char *outname;    /* Output file name                        */
  24.     char *p;        /* Temp pointer                            */
  25.     long now;        /* Timestamp in seconds                    */
  26.     char timestamp[255];    /* Timestamp in ascii            */
  27.     extern char *getmacro ();
  28.     extern char *obj ();
  29.     extern char *prargs ();
  30.     extern char *princs ();
  31.     
  32.  
  33.     /*
  34.       * Open the output file.  Use stdout if no filename is available.
  35.      */
  36.     if ((outname = getmacro ("MAKEFILE")) == NULL || *outname == EOS)
  37.         {
  38.         smacro ("MAKEFILE", "");
  39.         out = stdout;
  40.         outname = "";
  41.         }
  42.     else
  43.         {
  44.         progress ("Creating output file \"%s\"…\n", outname);
  45.         if ((out = fopen (outname, "w")) == NULL)
  46.             {
  47.             OSgoof ("Can't open \"%s\" for writing.\n", outname);
  48.             exit (EXIT_EXEC);
  49.             }
  50.         }
  51.     
  52.     /*
  53.      * Count the targets.
  54.      */
  55.     for (numt = 0; numt < TARGETMAX && targets[numt] != NULL; numt++)
  56.         ;
  57.  
  58.     
  59.     /*
  60.      * Build the #include dependencies, but don't output them yet;
  61.      * the first target must be a user-specified one.  We have to do
  62.      * this now to get the list of local include files.
  63.      */
  64.     makedepend ();
  65.     
  66.     if (*outname == EOS)
  67.         progress ("Writing makefile…\n");
  68.     else
  69.         progress ("Writing makefile to \"%s\"…\n", outname);
  70.         
  71.     /*
  72.      * Print out a header comment.
  73.      */
  74.     GetDateTime (&now);
  75.     IUTimeString (now, true, timestamp);
  76.     fprintf (out, "# This makefile was produced at %s ", timestamp);
  77.     IUDateString (now, abbrevDate, timestamp);
  78.     fprintf (out, "on %s by\n", timestamp);
  79.     fprintf (out, "# Makemake version 1.1, by Rick Holzgrafe, 12/10/86\n\n");
  80.     
  81.     /*
  82.      * Print out a macro reproducing the Makemake command line.
  83.      */
  84.     fprintf (out, "MAKEMAKE =");
  85.     prlist (out, argv, argc, prargs);
  86.     fprintf (out, "\n\n");
  87.     
  88.     /*
  89.      * Print a macro listing all the targets.
  90.      */
  91.     fprintf (out, "TARGETS =");
  92.     prlist (out, targets, TARGETMAX, NULL);
  93.     fprintf (out, "\n\n");
  94.     
  95.     /*
  96.      * Print a macro listing all the local include files
  97.      * (this list was made during the call to makedepend() above).
  98.      */
  99.     fprintf (out, "DOT_H =");
  100.     prlist (out, dot_h, DOTHMAX, NULL);
  101.     fprintf (out, "\n\n");
  102.     
  103.     /*
  104.      * Print a macro listing all the source files.
  105.      */
  106.     fprintf (out, "SRCS =");
  107.     prlist (out, sources, SOURCEMAX, NULL);
  108.     fprintf (out, "\n\n");
  109.     
  110.     /*
  111.      * Print macros listing all the object files.
  112.      * There is one such macro and list for each target.
  113.      * If there is more than one target, the macro names
  114.      * are "OBJS_" suffixed by the target name; if just one
  115.      * target, the one macro is just "OBJS".
  116.      */
  117.     if (numt == 1)
  118.         {
  119.         fprintf (out, "OBJS =");
  120.         prlist (out, objects[0], SOURCEMAX, NULL);
  121.         fprintf (out, "\n\n");
  122.         }
  123.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  124.         {
  125.         fprintf (out, "OBJS_%s =", targets[t]);
  126.         prlist (out, objects[t], SOURCEMAX, NULL);
  127.         fprintf (out, "\n\n");
  128.         }
  129.     
  130.     /*
  131.      * Print macros listing all the libraries.
  132.      * There is one such macro and list for each target.
  133.      * If there is more than one target, the macro names
  134.      * are "LIBS_" suffixed by the target name; if just one
  135.      * target, the one macro is just "LIBS".
  136.      */
  137.     if (numt == 1)
  138.         {
  139.         fprintf (out, "LIBS =");
  140.         prlist (out, liblist[0], LIBMAX, NULL);
  141.         fprintf (out, "\n\n");
  142.         }
  143.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  144.         {
  145.         fprintf (out, "LIBS_%s =", targets[t]);
  146.         prlist (out, liblist[t], LIBMAX, NULL);
  147.         fprintf (out, "\n\n");
  148.         }
  149.     
  150.     /*
  151.      * Print macros listing all the resource sources.
  152.      * There is one such macro and list for each target.
  153.      * If there is more than one target, the macro names
  154.      * are "RES_" suffixed by the target name; if just one
  155.      * target, the one macro is just "RES".
  156.      */
  157.     if (numt == 1)
  158.         {
  159.         fprintf (out, "RES =");
  160.         prlist (out, reslist[0], RESMAX, NULL);
  161.         fprintf (out, "\n\n");
  162.         }
  163.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  164.         {
  165.         fprintf (out, "RES_%s =", targets[t]);
  166.         prlist (out, reslist[t], RESMAX, NULL);
  167.         fprintf (out, "\n\n");
  168.         }
  169.     
  170.     /*
  171.      * Print macros listing all the dependencies.
  172.      * There is one such macro and list for each target.
  173.      * If there is more than one target, the macro names
  174.      * are "DEPS_" suffixed by the target name; if just one
  175.      * target, the one macro is just "DEPS".
  176.      */
  177.     if (numt == 1)
  178.         {
  179.         fprintf (out, "DEPS =");
  180.         prlist (out, deplist[0], DEPENDMAX, NULL);
  181.         fprintf (out, "\n\n");
  182.         }
  183.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  184.         {
  185.         fprintf (out, "DEPS_%s =", targets[t]);
  186.         prlist (out, deplist[t], DEPENDMAX, NULL);
  187.         fprintf (out, "\n\n");
  188.         }
  189.     
  190.     /*
  191.      * Print a macro listing all the Asm, C, and Pascal include directories.
  192.      */
  193.     fprintf (out, "A_INCDIRS =");
  194.     prlist (out, adirlist, DIRMAX, princs);
  195.     fprintf (out, "\n\n");
  196.     fprintf (out, "C_INCDIRS =");
  197.     prlist (out, cdirlist, DIRMAX, princs);
  198.     fprintf (out, "\n\n");
  199.     fprintf (out, "P_INCDIRS =");
  200.     prlist (out, pdirlist, DIRMAX, princs);
  201.     fprintf (out, "\n\n");
  202.     
  203.     /*
  204.      * Print out the AOptions macro.
  205.      * AOptions gets special attention: it gets the string "{A_INCDIRS}"
  206.      * appended.
  207.      */
  208.     p = getmacro ("AOptions");
  209.     if (p == NULL)
  210.         p = "";
  211.     fprintf (out, "%-12s = %s",
  212.         "AOptions", p);
  213.     fprintf (out, " {A_INCDIRS}\n\n");
  214.     
  215.     /*
  216.      * Print out the COptions macro.
  217.      * COptions gets special attention: it gets the string "{C_INCDIRS}"
  218.      * appended.
  219.      */
  220.     p = getmacro ("COptions");
  221.     if (p == NULL)
  222.         p = "";
  223.     fprintf (out, "%-12s = %s",
  224.         "COptions", p);
  225.     fprintf (out, " {C_INCDIRS}\n\n");
  226.     
  227.     /*
  228.      * Print out the POptions macro.
  229.      * POptions gets special attention: it gets the string "{P_INCDIRS}"
  230.      * appended.
  231.      */
  232.     p = getmacro ("POptions");
  233.     if (p == NULL)
  234.         p = "";
  235.     fprintf (out, "%-12s = %s",
  236.         "POptions", p);
  237.     fprintf (out, " {P_INCDIRS}\n\n");
  238.     
  239.     /*
  240.      * Print out the rest of the macros, which are not
  241.      * lists of files.  Most are just printed verbatim.
  242.      */
  243.     for (i = 0; i < MACROMAX && macrolist[i].mname != NULL; i++)
  244.         {
  245.         if (strcmp (macrolist[i].mname, "COptions") != 0)
  246.             {
  247.             fprintf (out, "%-12s = %s\n",
  248.                 macrolist[i].mname, macrolist[i].mvalue);
  249.             }
  250.         }
  251.     fprintf (out, "\n");
  252.     
  253.     /*
  254.      * Prepare to print the targets, their dependencies, and their
  255.      * productions.
  256.      */
  257.     if (numt == 1)
  258.         {
  259.         /*
  260.          * If there is just one target, print it out.
  261.          */
  262.         fprintf (out, "\n%s\tƒ", targets[0]);
  263.         if (reslist[0][0] != NULL)
  264.             {
  265.             fprintf (out, " {OBJS} {LIBS} %s.r.o {DEPS}\n",
  266.                 targets[0]);
  267.             fprintf (out, "\t{DUP} {DUPOPTS} %s.r.o {LINKTEMP}\n", targets[0]);
  268.             }
  269.         else
  270.             fprintf (out, " {OBJS} {LIBS} {DEPS}\n");
  271.         fprintf (out, "\t{LINK} {LINKOPTS} -o {LINKTEMP} {OBJS} {LIBS}\n",
  272.             targets[0]);
  273.         fprintf (out, "\t{RENAME} {RENAMEOPTS} {LINKTEMP} {Targ}\n");
  274.         fprintf (out, "\t{POST} {POSTOPTS} {Targ} {POSTARGS}\n");
  275.         }
  276.     else
  277.         {
  278.         /*
  279.          * If there are multiple targets, print first a production
  280.          * "all" which depends on the targets, then print the 
  281.          * productions for the targets.
  282.          */
  283.         fprintf (out, "all\tƒ");
  284.         for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  285.             fprintf (out, " %s", targets[t]);
  286.         fprintf (out, "\n\n");
  287.         for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  288.             {
  289.             fprintf (out, "\n%s\tƒ", targets[t]);
  290.             if (reslist[0][0] != NULL)
  291.                 {
  292.                 fprintf (out, " {OBJS_%s} {LIBS_%s} %s.r.o {DEPS_%s}\n",
  293.                     targets[t], targets[t], targets[t], targets[t]);
  294.                 fprintf (out, "\t{DUP} {DUPOPTS} %s.r.o {LINKTEMP}\n",
  295.                     targets[t]);
  296.                 }
  297.             else
  298.                 fprintf (out, " {OBJS_%s} {LIBS_%s} {DEPS_%s}\n",
  299.                     targets[t], targets[t], targets[t]);
  300.             fprintf (out, "\t{LINK} {LINKOPTS} -o {LINKTEMP} ");
  301.             fprintf (out, "{OBJS_%s} {LIBS_%s}\n",
  302.                 targets[t], targets[t]);
  303.             fprintf (out, "\t{RENAME} {RENAMEOPTS} {LINKTEMP} {Targ}\n");
  304.             fprintf (out, "\t{POST} {POSTOPTS} {Targ} {POSTARGS}\n");
  305.             }
  306.         }
  307.     fprintf (out, "\n\n");
  308.  
  309.     /*
  310.      * For targets with resource dependencies, output a production
  311.      * for making the resource fork.
  312.      */
  313.     if (numt == 1)
  314.         {
  315.         if (reslist[0][0] != NULL)
  316.             {
  317.             fprintf (out, "%s.r.o\tƒ {RES}", targets[0]);
  318.             for (i = 0; i < RESMAX && reslist[0][i] != NULL; i++)
  319.                 depend (out, reslist[0][i]);
  320.             fprintf (out, "\n\t{REZ} {REZOPTS} {TARG} {RES}\n\n");
  321.             }
  322.         }
  323.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  324.         {
  325.         if (reslist[t][0] != NULL)
  326.             {
  327.             fprintf (out, "%s.r.o\tƒ {RES_%s}", targets[t], targets[t]);
  328.             for (i = 0; i < RESMAX && reslist[t][i] != NULL; i++)
  329.                 depend (out, reslist[t][i]);
  330.             fprintf (out, "\n\t{REZ} {REZOPTS} {TARG} {RES_%s}\n\n",
  331.                 targets[t]);
  332.             }
  333.         }
  334.         
  335.     /*
  336.      * Boilerplate for assorted small-scale useful productions
  337.      */
  338.     fprintf (out, "{MAKEFILE}\tƒ NoneSuchFile\n");
  339.     fprintf (out, "NoneSuchFile\tƒ\n\t{MAKEMAKE}\n\n");
  340.     
  341.     fprintf (out, "clean\tƒ\n\t{DELETE} {DELETEOPTS} ");
  342.     if (numt == 1)
  343.         fprintf (out, " {OBJS}");
  344.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  345.         fprintf (out, " {OBJS_%s}", targets[t]);
  346.     fprintf (out, "\n\n");
  347.     
  348.     fprintf (out, "clobber\tƒ clean\n\t{DELETE} {DELETEOPTS} {TARGETS}\n\n");
  349.     
  350.     fprintf (out, "count\tƒ\n\t{COUNT} {COUNTOPTS} {DOT_H} {SRCS}\n\n");
  351.     
  352.     fprintf (out,
  353.         "files\tƒ\n\t{FILES} {FILESOPTS} {TARGETS} {DOT_H} {SRCS}");
  354.     if (numt == 1)
  355.         fprintf (out, " {OBJS}");
  356.     else for (t = 0; t < TARGETMAX && targets[t] != NULL; t++)
  357.         fprintf (out, " {OBJS_%s}", targets[t]);
  358.     fprintf (out, " {MAKEFILE}\n\n");
  359.     
  360.     fprintf (out,
  361.         "print\tƒ\n\t{PRINT} {PRINTOPTS} {DOT_H} {SRCS} {MAKEFILE}\n\n");
  362.     
  363.     fprintf (out,
  364.         "tags\tƒ {DOT_H} {SRCS}\n\t{CTAGS} {CTAGSOPTS} {C_INCDIRS} {NewerDeps}\n\n");
  365.         
  366.     /*
  367.      * Now at last we can print out the #include dependencies
  368.      * which were generated at the top of this routine.
  369.      */
  370.     getdepend (out);
  371.     
  372.     /*
  373.      * Close the file, and set it to type 'TEXT'.
  374.      */
  375.     fclose (out);
  376.     setfile (outname);
  377.  
  378.     /*
  379.      * Done!
  380.      */
  381.     }
  382.  
  383. /*
  384.  * Create a temporary file in which to write the list of include 
  385.  * dependencies.  (We must create the list early to learn about it,
  386.  * but output it late, so its productions come after the default ones
  387.  * and the more interesting ones.)  Then call depend() on each source
  388.  * file to generate the list.
  389.  */
  390. makedepend ()
  391.     {
  392.     int i;
  393.  
  394.     /*
  395.      * Create a temp file for reading and writing.
  396.      */
  397.     dpndfile = "Makemake.temp";
  398.     progress ("Creating temporary file \"%s\"…\n", dpndfile);
  399.     if ((dpndf = fopen (dpndfile, "w+")) == NULL)
  400.         {
  401.         OSgoof ("Can't create \"%s\" for reading and writing.\n",
  402.             dpndfile);
  403.         exit (EXIT_EXEC);
  404.         }
  405.     
  406.     /*
  407.      * For each source file, run depend() to list its
  408.      * #include dependencies.
  409.      */
  410.     for (i = 0; i < SOURCEMAX && sources[i] != NULL; i++)
  411.         {
  412.         depend (dpndf, sources[i]);
  413.         fprintf (dpndf, "\n");
  414.         }
  415.     }
  416.  
  417. /*
  418.  * Print the temp file (which holds the list of #include dependencies)
  419.  * to the given output, then remove the temp file.
  420.  */
  421. getdepend (out)
  422. FILE *out;
  423.     {
  424.     int sz;
  425.     char buf[BUFSIZ];
  426.     
  427.     rewind (dpndf);
  428.     while ((sz = fread (buf, 1, BUFSIZ, dpndf)) != 0)
  429.         fwrite (buf, 1, sz, out);
  430.     fclose (dpndf);
  431.     progress ("Removing temporary file \"%s\"…\n", dpndfile);
  432.     unlink (dpndfile);
  433.     }
  434.  
  435. /*
  436.  * Given a source filename, generate the corresponding object file name.
  437.  * The object file name is returned in a re-usable buffer, and so 
  438.  * must be copied somewhere safe by the caller if the name is to be saved.
  439.  */
  440. char *obj (s)
  441. char *s;
  442.     {
  443.     static char buf[LINELEN];
  444.     
  445.     strncpy (buf, s, LINELEN);
  446.     buf[LINELEN - 3] = EOS;
  447.     strcat (buf, ".o");
  448.     
  449.     return (buf);
  450.     }
  451.  
  452. prlist (out, list, max, prfunc)
  453. FILE *out;
  454. char *list[];
  455. int max;
  456. char *(*prfunc)();
  457.     {
  458.     int i;
  459.     int len;
  460.     int linelen = 0;
  461.     char *p;
  462.     
  463.     for (i = 0; i < max && list[i] != NULL; i++)
  464.         {
  465.         if (prfunc != NULL)
  466.             {
  467.             p = prfunc (list[i]);
  468.             len = strlen (p);
  469.             }
  470.         else
  471.             {
  472.             len = strlen (list[i]) + 1;
  473.             p = NULL;
  474.             }
  475.             
  476.         if (linelen + len > 50)
  477.             {
  478.             fprintf (out, " ∂\n\t");
  479.             linelen = len;
  480.             }
  481.         else
  482.             linelen += len;
  483.         
  484.         if (p != NULL)
  485.             fprintf (out, "%s", p);
  486.         else
  487.             fprintf (out, " %s", list[i]);
  488.         }
  489.     }
  490.  
  491. /*
  492.  * Format the given string (in this case, prefix a space and put
  493.  * single quotes around it) and return a pointer to it in a 
  494.  * re-usable buffer.
  495.  */
  496. char *prargs (s)
  497. char *s;
  498.     {
  499.     static char buf[LINELEN];
  500.     
  501.     sprintf (buf, " '%s'", s);
  502.     return (buf);
  503.     }
  504.  
  505. char *princs (s)
  506. char *s;
  507.     {
  508.     static char buf[LINELEN];
  509.     
  510.     sprintf (buf, " -i %s", s);
  511.     return (buf);
  512.     }
  513.